home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-04-20 | 8.3 KB | 351 lines | [TEXT/PJMM] |
- program Talk;
-
- { This program was written by Peter N Lewis, Mar 1992 in THINK Pascal 4.0.1 }
-
- uses
- TalkdTypes, TCPTypes, TCPStuff, UDPStuff;
-
- label
- 999; { bail out }
-
- const
- ctl_wait = 2;
-
- var
- my_machine_addr, his_machine_addr: longInt;
- my_machine_name, his_machine_name: str255;
- my_name, his_name: userStr;
- my_tty, his_tty: ttyStr;
- ctl_socket, socket: integer;
- invitation_waiting: boolean;
- talkc: TCPConnectionPtr;
- talkuc: UDPConnectionPtr;
- dnrptr: ptr;
- quitNow: boolean;
-
- procedure WNE (var er: eventRecord);
- var
- dummy: boolean;
- begin
- dummy := WaitNextEvent(everyEvent, er, 15, nil);
- if er.what = keyDown then begin
- if BAND(er.message, $FF) = ord('q') then
- quitNow := true;
- end;
- end;
-
- function AddrToName (ip: longInt; var name: str255): OSErr;
- var
- hi: hostInfo;
- done: signedByte;
- oe: OSErr;
- er: eventRecord;
- begin { XXX }
- { oe := TCPAddrToName(dnrptr, m.ctl_addr.ip, hi, done);}
-
- TCPAddrToStr(dnrptr, ip, hi.rtnHostName);
- oe := 0;
- hi.rtnCode := oe;
- done := 1;
-
- if oe = noErr then begin
- while done = 0 do
- WNE(er);
- oe := hi.rtnCode;
- end;
- name := hi.rtnHostName;
- AddrToName := oe;
- end;
-
- function OpenSocket: OSErr;
- var
- localhost, remotehost: longInt;
- remoteport: integer;
- available: longInt;
- state: integer;
- oe: OSErr;
- begin
- oe := TCPPassiveOpen(talkc, 0, 0, 0, nil);
- if oe = noErr then begin
- repeat
- TCPRawState(talkc, state, localhost, socket, remotehost, remoteport, available);
- until socket <> 0;
- end;
- OpenSocket := oe;
- end;
-
- function OpenCtl: OSErr;
- var
- oe: OSErr;
- begin
- ctl_socket := 0;
- oe := UDPCreate(talkuc, 0, ctl_socket);
- OpenCtl := oe;
- end;
-
- procedure GetNames (user, tty, mach: str255);
- var
- rtnStruct: hostInfo;
- done: signedByte;
- oe: OSErr;
- er: eventRecord;
- begin
- writeln('Talk to ', user, '@', mach, ' on tty ', tty);
- oe := TCPGetMyIPAddr(my_machine_addr);
- TCPAddrToStr(dnrptr, my_machine_addr, my_machine_name);
- my_name := 'peteraaaaaaa';
- my_name[6] := chr(0);
- my_tty[1] := chr(0);
-
- oe := TCPStrToAddr(dnrptr, mach, rtnStruct, done);
- if oe = noErr then begin
- while done = 0 do
- WNE(er);
- oe := rtnStruct.rtnCode;
- his_machine_addr := rtnStruct.addrs[1];
- end;
- TCPAddrToStr(dnrptr, his_machine_addr, his_machine_name);
- his_name := user;
- his_tty := tty;
- end;
-
- procedure CtlSend (target: longInt; id: integer; typ: ctlTypes);
- var
- m: ctlMsg;
- oe: OSErr;
- begin
- writeln('Send to ', pointer(target), ',', id, ' - ', typ);
- m.vers := talk_version;
- m.typ := typ;
- m.id_num := id;
- m.l_name := my_name;
- m.r_name := his_name;
- m.r_tty := his_tty;
- m.addr.family := AF_INET;
- m.addr.ip := my_machine_addr;
- m.addr.port := socket;
- m.ctl_addr.family := AF_INET;
- m.ctl_addr.ip := my_machine_addr;
- m.ctl_addr.port := ctl_socket;
- oe := UDPWrite(talkuc, target, talk_socket, @m, SizeOf(m), false);{target}
- end;
-
- procedure CtlTransact (target: longInt; id: integer; typ: ctlTypes; var r: ctlResponse);
- var
- datap: ptr;
- datalen: integer;
- remoteIP, f: longInt;
- remopteport: integer;
- oe: OSErr;
- er: eventRecord;
- begin
- writeln('CtlTransact to ', pointer(target), ',', id, ' - ', typ);
- repeat
- f := TickCount;
- CtlSend(target, id, typ);
- repeat
- if TickCount > f + 60 * ctl_wait then begin
- CtlSend(target, id, typ);
- f := TickCount;
- end;
- WNE(er);
- until UDPDatagramsAvailable(talkuc) > 0;
- repeat
- oe := UDPRead(talkuc, 2, remoteIP, remopteport, datap, datalen);
- if oe = noErr then begin
- if datalen <> SizeOf(r) then
- oe := -1
- else
- BlockMove(datap, @r, datalen);
- if datalen > 0 then
- oe := UDPReturnBuffer(talkuc, datap);
- end;
- until (UDPDatagramsAvailable(talkuc) <= 0) or ((r.vers = talk_version) and (r.typ = typ));
- until (r.vers = talk_version) and (r.typ = typ);
- r.id_num := r.id_num;
- r.addr.family := r.addr.family;
- writeln('CtlTransact returns ', r.answer);
- end;
-
- var
- local_id, remote_id: integer;
-
- function GetAnswer (a: answers): str255;
- begin
- case a of
- A_success:
- GetAnswer := 'Success';
- A_not_here:
- GetAnswer := 'Your party is not logged on';
- A_failed:
- GetAnswer := 'Target machine is too confused to talk to us';
- A_machine_unknown:
- GetAnswer := 'Target machine does not recognize us';
- A_permission_denied:
- GetAnswer := 'Your party is refusing messages';
- A_unknown_request:
- GetAnswer := 'Target machine can not handle remote talk';
- A_badversion:
- GetAnswer := 'Target machine indicates protocol mismatch';
- A_badaddr:
- GetAnswer := 'Target machine indicates protocol botch (addr)';
- A_badctladdr:
- GetAnswer := 'Target machine indicates protocol botch (ctl_addr)';
- otherwise
- GetAnswer := 'Unknown Answer';
- end;
- end;
-
- procedure AnnounceInvite (id: integer);
- var
- response: ctlresponse;
- begin
- CtlTransact(his_machine_addr, id, CT_announce, response);
- remote_id := response.id_num;
- if response.answer <> A_success then begin
- writeln(GetAnswer(response.answer));
- goto 999;
- end;
- CtlTransact(my_machine_addr, id, CT_leave_invite, response);
- local_id := response.id_num;
- end;
-
- procedure InviteRemote;
- { Wait for connection on talkc, then delete invitations }
- var
- f: longInt;
- response: ctlResponse;
- er: eventRecord;
- begin
- AnnounceInvite(-1);{id_num=}
- invitation_waiting := true;
- f := TickCount;
- while (TCPState(talkc) = T_Listening) and not quitNow do begin
- if TickCount > f + 60 * RING_WAIT then begin
- writeln('Ringing your party again');
- AnnounceInvite(remote_id + 1);
- f := TickCount;
- end;
- WNE(er);
- end;
- CtlTransact(my_machine_addr, local_id, CT_delete, response);
- CtlTransact(his_machine_addr, remote_id, CT_delete, response);
- invitation_waiting := false;
- end;
-
- procedure SendDelete;
- begin
- CtlSend(his_machine_addr, remote_id, CT_delete);
- CtlSend(my_machine_addr, local_id, CT_delete);
- end;
-
- function LookForInvite (var r: ctlResponse): boolean;
- begin
- writeln('Checking for invitation on caller''s machine');
- CtlTransact(his_machine_addr, remote_id, CT_lookup, r);
- if r.answer = A_success then begin
- remote_id := r.id_num;
- LookForInvite := true;
- end
- else
- LookForInvite := false;
- end;
-
- function CheckLocal: boolean;
- var
- response: ctlResponse;
- oe, ooe: OSErr;
- er: eventRecord;
- begin
- writeln('CheckLocal');
- if not LookForInvite(response) then begin
- CheckLocal := false;
- exit(CheckLocal);
- end;
- writeln('Waiting to connect with caller');
- oe := TCPClose(talkc, @ooe);
- while (oe = noErr) and (ooe = inProgress) do
- WNE(er);
- writeln(oe, ooe);
- writeln(TCPRelease(talkc));
- writeln(TCPActiveOpen(talkc, 0, response.addr.ip, response.addr.port, nil));
- while TCPState(talkc) = T_WaitingForOpen do
- WNE(er);
- if TCPState(talkc) <> T_Established then begin
- CtlTransact(his_machine_addr, remote_id, CT_delete, response);
- writeln(OpenSocket);
- CheckLocal := false;
- end;
- end;
-
- procedure Talk;
- const
- buf_siz = 50;
- var
- buf: string[buf_siz];
- len: longInt;
- er: eventRecord;
- dummy: boolean;
- oe: OSErr;
- begin
- if not quitNow then
- writeln('Connection Established ', TCPSTate(talkc));
- while not quitNow do begin
- len := TCPCharsAvailable(talkc);
- if len > 0 then begin
- if len > buf_siz then
- len := buf_siz;
- {$PUSH}
- {$R-}
- oe := TCPReceiveChars(talkc, @buf[1], len);
- buf[0] := chr(len);
- writeln('Received:', buf);
- {$POP}
- end;
- WNE(er);
- if er.what = keyDown then begin
- writeln('Send:', chr(BAND(er.message, $FF)));
- oe := TCPSendAsync(talkc, ptr(longInt(@er.message) + 3), 1, nil);
- end;
- end;
- end;
-
- var
- oe, ooe: OSErr;
- s: str255;
- er: eventRecord;
- r: rect;
- ip: longInt;
- begin
- SetRect(r, 10, 40, 500, 300);
- { SetTextRect(r);}
- ShowText;
- quitNow := false;
- writeln(UDPInit);
- writeln(TCPInit);
- s := '';
- writeln(TCPOpenResolver(s, dnrptr));
- invitation_waiting := false;
- writeln(TCPGetMyIPAddr(ip));
- if ip = $86073203 then
- GetNames('peter', '', '134.7.50.4')
- else
- GetNames('peter', '', '134.7.50.3');
- writeln(OpenCtl);
- writeln(OpenSocket);
- if not CheckLocal then
- InviteRemote;
- Talk;
- 999:
- if invitation_waiting then
- SendDelete;
- oe := TCPClose(talkc, @ooe);
- while (oe = noErr) and (ooe = inProgress) do
- WNE(er);
- writeln(oe, ooe);
- writeln(TCPRelease(talkc));
- writeln(UDPRelease(talkuc));
- TCPCloseResolver(dnrptr);
- TCPFinish;
- UDPFinish;
- end.